﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;

namespace library
{
    class IndexItem 
    {
        internal string Term;

        internal ValueHits<IndexItem> References = new ValueHits<IndexItem>();

        internal List<byte[]> Addresses = new List<byte[]>();

        IndexItem(string term, ValueHits<IndexItem> references, List<byte[]> addresses)
        {
            term = Term;

            References = references;

            Addresses = addresses;
        }

        internal IndexItem(string term, byte[] address, IndexItem reference = null)
        {
            Term = term;

            AddAddress(address);

            if (reference != null)
                AddReference(reference);
        }

        internal void AddReference(IndexItem item, bool stop = false)
        {
            References.Add(item);

            if (!stop)
                item.AddReference(this, true);
        }

        internal void GetReferences(ValueHits<IndexItem> hits, byte steps = Parameters.semanticSearchSteps)
        {
            steps--;

            var items = References.OrderByDescending(x => x.Hits);

            foreach (var item in items)
            {
                IndexItem i = LocalIndex.Get(item.HitValue.Term);

                //ignore reference hits on search results
                hits.Add(item);

                if (steps > 0)
                    i.GetReferences(hits, steps);
            }
        }

        internal void AddAddress(byte[] address)
        {
            lock (Addresses)
                Addresses.Add(address);
        }

        #region FromBytes

        internal static void Load(string filename)
        {
            using (var stream = new FileStream(filename, FileMode.Open, FileAccess.Read))
            {
                byte[] address = Utils.ReadBytes(stream);

                byte[] addresses = Utils.ReadBytes(stream);

                byte[] references = Utils.ReadBytes(stream);

                // AddressesFromBytes(address, addresses);

                //ReferencesFromBytes(address, references);
            }
        }

        //static void ReferencesFromBytes(byte[] address, byte[] references)
        //{
        //    int offset = 0;

        //    while (offset < references.Length)
        //    {
        //        byte[] reference = Utils.ReadBytes(references, offset);

        //        offset += 4 + reference.Length; //4 = reference length bytes

        //        byte reference_value = references[offset];

        //        offset++;

        //        LocalIndex.AddReference(address, reference, reference_value);
        //    }
        //}

        //static void AddressesFromBytes(byte[] address, byte[] addresses)
        //{
        //    int offset = 0;

        //    while (offset < addresses.Length)
        //    {
        //        byte[] address_ref = Utils.ReadBytes(addresses, offset);

        //        offset += 4 + address_ref.Length;

        //        LocalIndex.AddAddress(address, address_ref);
        //    }
        //}

        #endregion

        #region ToBytes

        //internal void Save()
        //{
        //    File.WriteAllBytes(Path.Combine(Parameters.localPacketsDir, Utils.ToBase64Address(Term)), ToBytes());
        //}

        //public byte[] ToBytes()
        //{
        //    List<byte> buffer = new List<byte>();


        //    buffer.Add((byte)PacketTypes.Index);

        //    buffer.AddRange(BitConverter.GetBytes(Term.Length));

        //    buffer.AddRange(Term);


        //    byte[] address = AddressesToBytes();

        //    buffer.AddRange(BitConverter.GetBytes(address.Length));

        //    buffer.AddRange(address);


        //    byte[] references = ReferencesToBytes();

        //    buffer.AddRange(BitConverter.GetBytes(references.Length));

        //    buffer.AddRange(references);


        //    return buffer.ToArray();

        //}

        //byte[] ReferencesToBytes()
        //{
        //    var buffer = new List<byte>();

        //    foreach (var item in References)
        //    {
        //        buffer.AddRange(BitConverter.GetBytes(item.Value.Length));

        //        buffer.AddRange(item.Value);

        //        buffer.Add(item.Hits);
        //    }

        //    return buffer.ToArray();
        //}

        //byte[] AddressesToBytes()
        //{
        //    List<byte> buffer = new List<byte>();

        //    foreach (byte[] address in Addresses)
        //    {
        //        buffer.AddRange(BitConverter.GetBytes(address.Length));
        //        buffer.AddRange(address);
        //    }

        //    return buffer.ToArray();
        //}

        #endregion

        public bool Equals(IndexItem value)
        {
            return this.Term.Contains(value.Term);
        }

    }

    class IndexItemField
    {
        internal byte[] Value;

        internal List<byte[]> Addresses = new List<byte[]>();

        internal IndexItemField(byte[] value, byte[] address)
        {
            if (value == null)
                value = Encoding.Unicode.GetBytes("Content");

            Value = value;

            Addresses.Add(address);
        }
    }
}
